﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Simp.Model.CoreExpressions.Sequences
{
	/// <summary>Adaptor of <see cref="ISequenceAccessor"/> simplifying it synchronously (on the calling thread).</summary>
	public class SyncSimplifyingSequenceAccessor : ISequenceAccessor
	{
		private readonly SimplificationMode _simplificationMode;
		private readonly ISequenceAccessor _innerAccessor;

		/// <summary>Constructor taking an <see cref="ISequenceAccessor"/> in parameter.</summary>
		/// <param name="innerAccessor"/>
		public SyncSimplifyingSequenceAccessor(ISequenceAccessor innerAccessor)
			: this(SimplificationMode.PerfectEquivalent, innerAccessor)
		{
		}

		/// <summary>Constructor taking an <see cref="ISequenceAccessor"/> in parameter.</summary>
		/// <param name="simplificationMode"/>
		/// <param name="innerAccessor"/>
		public SyncSimplifyingSequenceAccessor(SimplificationMode simplificationMode, ISequenceAccessor innerAccessor)
		{
			if (innerAccessor == null)
			{
				throw new ArgumentNullException("innerAccessor");
			}
			_simplificationMode = simplificationMode;
			_innerAccessor = innerAccessor;
		}

		#region ISequenceAccessor Members
		int ISequenceAccessor.Count
		{
			get { return _innerAccessor.Count; }
		}

		IExpression ISequenceAccessor.this[int index]
		{
			get { throw new NotSupportedException("This accessor is meant to be accessed by enumeration not randomly"); }
		}
		#endregion

		#region IEnumerable<IFunction> Members
		IEnumerator<IExpression> IEnumerable<IExpression>.GetEnumerator()
		{
			foreach (IExpression expression in _innerAccessor)
			{
				IExpression simplifiedExpression = ExpressionHelper.Simplify(false, expression, _simplificationMode);

				yield return simplifiedExpression;
			}
		}
		#endregion

		#region IEnumerable Members
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<IExpression>)this).GetEnumerator();
		}
		#endregion
	}
}